package com.sghd.fight.module.game.service.room;

import com.sghd.common.utils.ManagedException;
import com.sghd.common.utils.json.JsonUtils;
import com.sghd.common.utils.math.RandomUtils;
import com.sghd.common.utils.model.RatioProbability;
import com.sghd.fight.module.game.config.LevelConfig;
import com.sghd.fight.module.game.config.SkillConfig;
import com.sghd.fight.module.game.core.ChessBoard;
import com.sghd.fight.module.game.core.model.BattleSkill;
import com.sghd.fight.module.game.core.model.Buff;
import com.sghd.fight.module.game.core.model.Unit;
import com.sghd.fight.module.game.core.model.UnitState;
import com.sghd.fight.module.game.event.GameServerEvent;
import com.sghd.fight.module.game.event.PushEvent;
import com.sghd.fight.net.SocketEnum;
import com.sghd.fight.utils.Callback;
import com.sghd.pojo.fight.game.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * @author frank
 * @date 2018-10-22 16:16
 * @desc 玩家
 **/
public class Player extends Unit {
    private Logger logger = LoggerFactory.getLogger(getClass());
    public static final int LEFT = 0;
    public static final int RIGHT = 1;
    /** 索引(区分玩家位置)*/
    private int index = -1;
    /** 大厅上阵技能池*/
    private Map<Integer, Integer> level2Skill = new HashMap<>();
    /** 五行对应等级*/
    private Map<ChessType, Integer> element2Level = new HashMap<>();
    /** 重置技能次数，前三次免费*/
    private int resetSkill = 0;
    /** 玩家金币*/
    private long money;

    private ChessBoard chessBoard;

    public Player(long playerId, String name, int index, IRoom room, Map<Integer, Integer> level2Skill, Map<ChessType, Integer> element2Level, long money) {
        super(playerId, name, room);
        //初始化魔法值
        this.index = index;
        this.type = UnitEnum.PLAYER;
        this.level2Skill = level2Skill;
        this.element2Level = element2Level;
        this.money = money;
        this.chessBoard = room.getChessBoard();
    }

    public Player(long playerId, String name, int index, IRoom room, Map<Integer, Integer> level2Skill, Map<ChessType, Integer> element2Level, long money, LevelConfig levelConfig) {
        super(playerId, name, room);
        //初始化魔法值
        this.index = index;
        this.type = UnitEnum.PLAYER;
        this.level2Skill = level2Skill;
        this.element2Level = element2Level;
        this.money = money;
        for (ChessType chessType : ChessType.values()) {
            if (levelConfig.getMagics().containsKey(chessType)) {
                magic.update(chessType, levelConfig.getMagics().get(chessType));
            }
        }
    }


    @Override
    public void dead() {
        super.dead();
        //TODO 目标死亡，结算
    }

    public void initUpMagic() {
        Map<ChessType, Integer> map = new HashMap<>();
        for (ChessType chessType : ChessType.values()) {
            if (chessType == ChessType.CT_LIGHTNING) {
                continue;
            }
            map.put(chessType, 1);
        }
        RatioProbability<ChessType> ratioProbability = RatioProbability.valueOf(map);
        for (int i = 0; i < 5; i++) {
            ChessType type = ratioProbability.getResult();
            magic.collect(type);
        }
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public Map<Integer, Integer> getLevel2Skill() {
        return level2Skill;
    }

    public void setSkills(Map<Integer, BattleSkill> skills) {
        this.skills = skills;
    }

    public UnitVo reconn() {
        //移除离线状态
        removeState(UnitState.OFFLINE);
        UnitVo unitVo = new UnitVo(id, name);
        List<BattleSkillVo> skills = new ArrayList<>();
        for (BattleSkill battleSkill : this.skills.values()) {
            skills.add(battleSkill.toVo());
        }
        unitVo.setBattleSkills(skills);
        Map<UnitValue, Integer> values = new HashMap<>();
        values.put(UnitValue.HP, getValue(UnitValue.HP));
        values.put(UnitValue.HP_MAX, getValue(UnitValue.HP_MAX));
        unitVo.setValues(values);
        unitVo.setMagics(magic.getMagics());
        unitVo.setReady(ready);
        List<BuffVo> buffVos = new ArrayList<>();
        for (Buff buff : buffs.values()) {
            buffVos.add(buff.toVo());
        }
        unitVo.setBuffs(buffVos);

        unitVo.setTrustee(hasState(UnitState.TRUSTEE));
        unitVo.setRound(round);
        return unitVo;
    }

    @Override
    public UnitVo toVo() {
        UnitVo unitVo = super.toVo();
        unitVo.setMagics(magic.getMagics());
        Map<UnitValue, Integer> values = new HashMap<>();
        values.put(UnitValue.HP, getValue(UnitValue.HP));
        values.put(UnitValue.HP_MAX, getValue(UnitValue.HP_MAX));
        unitVo.setValues(values);
        unitVo.setMoney(money);
        unitVo.setElements(new HashMap<>(element2Level));
        return unitVo;
    }

    public Map<ChessType, Integer> getElement2Level() {
        return element2Level;
    }

    @Override
    public int getSkillLevel(int skillId) {
        Integer level = level2Skill.get(skillId);
        return level == null ? 0 : level;
    }

    public void resetSkill(Set<Integer> keeps) {
        for (Integer keep : keeps) {
            if (!skills.containsKey(keep)) {
                throw new ManagedException(-1, "包含未获得的技能！");
            }
        }
        room.post(GameServerEvent.NAME, GameServerEvent.valueOf(RsetSkillVo.valueOf(id, ++resetSkill, keeps == null ? 0 : keeps.size()),
                SocketEnum.HALL_RESET_SKILL, new Callback<RsetSkillVo>() {
                    @Override
                    public void call(RsetSkillVo body) {
                        if (body.getResult().getCode() != 0) {
                            onException(new RuntimeException(body.getResult().getBody() + ""), body);
                            return;
                        }
                        List<Integer> alls = new ArrayList(level2Skill.keySet());
                        if (keeps == null || keeps.isEmpty()) {
                            skills.clear();
                        } else {
                            Set<Integer> remove = new HashSet<>();
                            for (Integer tpl : skills.keySet()) {
                                if (!keeps.contains(Integer.valueOf(tpl))) {
                                    //移除未保留的
                                    remove.add(tpl);
                                }
                            }
                            alls.removeAll(keeps);
                            for (Integer rmv : remove) {
                                skills.remove(rmv);
                            }
                        }
                        Collections.shuffle(alls);
                        int deSize = skills.size();
                        for (int i = 0; i < 5 - deSize; i++) {
                            int skillId = alls.get(i);
                            int level = getSkillLevel(skillId);
                            SkillConfig skillConfig = room.getConfigService().getSkillConfig(skillId);
                            skills.put(skillId, new BattleSkill(skillId, skillConfig.getCool(getSkillLevel(skillId)), level));
                        }
                        List<BattleSkillVo> skillVos = new ArrayList<>();
                        for (BattleSkill battleSkill : skills.values()) {
                            skillVos.add(battleSkill.toVo());
                        }
                        Map<String, Object> rsponse = new HashMap<>();
                        rsponse.put("id", id);
                        rsponse.put("cost", body.getResult().getBody());
                        rsponse.put("battleSkills", skillVos);
                        logger.debug("玩家随机技能：{}", JsonUtils.object2String(skills.keySet()));
                        room.post(PushEvent.NAME, PushEvent.valueOf(Result.valueOf(rsponse), room.getUnits().keySet(), SocketEnum.RESET_SKILL));
                    }

                    @Override
                    public void onException(Exception ex, RsetSkillVo body) {
                        room.post(PushEvent.NAME, PushEvent.valueOf(Result.valueOf(-1, "重置技能失败[" + ex.getMessage() + "]！"), room.getUnits().keySet(), SocketEnum.RESET_SKILL));
                        logger.error("玩家[{}]重置技能失败!", id, ex);
                    }
                }));
    }

    /**
     */
    @Override
    public void action() {
        if (room.isOver()) {
            return;
        }
        if (room.getCurrent() != this || round <= 0) {
            return;
        }
        if (!hasState(UnitState.TRUSTEE)) {
            //不是托管中
            return;
        }
        int delay = RandomUtils.betweenInt(2000, 5000, true);
        if (room.getNextRound().getType() == UnitEnum.ROBOT) {
            //另一个玩家是机器人，防止服务器逻辑跑太快
            delay = room.getConfig().getRoundTime() - 6000;
        }
        delayAction(delay);
    }

    public void delayAction(int delay) {
        addWork(now -> {
            doAction();
            if (room.isOver()) {
                return;
            }
            //有剩余回合
            if (getRound() > 0) {
                int delayNext = RandomUtils.betweenInt(2000, 5000, true);
                Unit other = room.getNextRound();
                if (other == null) {
                    return;
                }
                if (other.getType() == UnitEnum.ROBOT) {
                    //另一个玩家是机器人，防止服务器逻辑跑太快
                    delayNext = room.getConfig().getRoundTime() - 6000;
                }
                delayAction(delayNext);
            }
        }, new Date(System.currentTimeMillis() + delay));
    }

    /**
     * 进入托管返回  然后执行交换
     * @return
     */

    public void doAction() {
        if (room.isOver()) {
            return;
        }
        if (room.getCurrent() != this || round <= 0) {
            return;
        }
        if (!hasState(UnitState.TRUSTEE)) {
            //不是托管中
            return;
        }
        if (first) {
            chessBoard.getRandom().setSeed(getNextSeed());
            first = false;
        }
        //双方玩家都托管
        if (room.getTrushees().size() == 2) {
            if (room.getTrusheeIndex() >= Integer.MAX_VALUE) {
                logger.debug("双方玩家托管 ！");
                room.gameOver(ExitReason.TRUSTEESHIP);
                return;
            } else {
                room.setTrusheeIndex(room.getTrusheeIndex() + 1);
            }
        } else {
            room.setTrusheeIndex(0);
        }
        List<List<Integer>> list = chessBoard.canElim(true);
        Collections.shuffle(list);
        //普通托管
        logger.debug("当前第[{}]回合，玩家[{}]托管行动[{}],[{}]！", room.getCountRound(), id, list.get(0).get(0), list.get(0).get(1));
        try {
            room.action(id, list.get(0).get(0), list.get(0).get(1));
        } catch (Exception e) {
            logger.debug("托管行动发生错误[{}]", e.getMessage());
        }
    }
}
